package org

import (
    "time"
	"strconv"
	"strings"
	"dhfshop/models/org"
	"dhfshop/models/misc"
	"dhfshop/utils/helper"
	"dhfshop/controllers/base"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
)

// 用户信息
type UserController struct {
	base.BaseController
}

func (this *UserController) Login() {
    var (
		curPartnerId   int64 = 0
		curPartnerName string
		curSubRoleId   int64 = 0
		curUserId      int64 = 0
		isDealer       int   = 0
		err            error
	)
	v := struct {
	    UserName  string  `form:"user_name" valid:"Required"`
		Password  string  `form:"password" valid:"Required"`
		PartnerId int64   `form:"partner_id"`
		DhfXid    string  `form:"dhfxid"`
		RefUserId int64   `form:"ref_user_id"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	// 第一次登录
	if v.PartnerId == 0 {
	    //系统存在用户	
		if user, err := org.GetUserByUsername(v.UserName); err == nil {
			passwordHashed := org.EncryptPassword(user.Salt, v.Password)
			if passwordHashed != user.PasswordHashed {
				this.ServeError("密码错误")
				return
			}
			if !user.Activated {
				this.ServeError("用户已经停用,请联系管理员")
				return 
			}
			if ok := strings.Contains(user.RoleIds, ","); ok {
				partnerIdNameArr := make(map[string]string) 
				for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
					roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
					if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
						if partner, err := org.GetPartnerById(role.PartnerId); err == nil {
						    partnerIdNameArr[strconv.FormatInt(role.PartnerId, 10)] = partner.Name
						}	
					}
				}
				partnerIdArr := []string{}
				for key, _ := range partnerIdNameArr {
					partnerIdArr = append(partnerIdArr, key)
				}
				rsp := struct {
					PartnerIds      string            `json:"partner_ids"`
					PartnerIdNames  map[string]string `json:"partner_id_names"`
				}{PartnerIds:strings.Join(partnerIdArr,","),PartnerIdNames:partnerIdNameArr}
				this.Data["json"] = rsp
				this.ServeJSON()
				return
			}else{
				curSubRoleId, _= strconv.ParseInt(user.RoleIds, 10, 64)
				if role, err := org.GetPartnerIdByRoleId(curSubRoleId); err == nil {
					curPartnerId = role.PartnerId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
				}
			}
		}else{
			this.ServeError("用户名不存在")
			return
		}
	}else{   //第二次登录
		user, err := org.GetUserByUsername(v.UserName)
		if err != nil {
		    this.ServeError(err.Error())
			return
		}
		passwordHashed := org.EncryptPassword(user.Salt, v.Password)
		if passwordHashed != user.PasswordHashed {
			this.ServeError("密码错误")
			return
		}
		// 屏蔽对手
		if !user.Activated {
		    this.ServeError("用户已经停用,请联系管理员")
		    return 
		}
		//
		for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
			roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
			if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
				if v.PartnerId == role.PartnerId {
					curPartnerId = role.PartnerId
					curSubRoleId = roleId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
					break
				}
			}
		}
		if curPartnerId == 0 {
			this.ServeError("partner_id is invalid")
			return
		}
	}
	/********create token************/
	token := jwt.New(jwt.GetSigningMethod("HS256"))
	claims := token.Claims.(jwt.MapClaims)
	claims["CurrentUser"] = struct {
	    Id        int
		CompanyId int
		Role      int
		SubRoleId int
		DhfxId    string
        IsDealer  int		
	}{Id:int(curUserId),CompanyId:int(curPartnerId),Role:2,SubRoleId:int(curSubRoleId),DhfxId:v.DhfXid,IsDealer:isDealer}
	claims["exp"] = time.Now().UTC().Add(time.Hour * 24 * 1).Unix()
	tokenSecret := beego.AppConfig.String("AuthTokenSecret")
	tokenString, err := token.SignedString([]byte(tokenSecret))
	if err != nil {
		this.ServeError("登录失败，请稍后再试")
		return
	}
	if partner, err := org.GetPartnerById(curPartnerId); err == nil {
	   curPartnerName = partner.Name
	}
	this.Data["json"] = map[string]string{
		"token": tokenString,
		"partner_id": strconv.FormatInt(curPartnerId, 10),
		"partner_name": curPartnerName,
	}
	this.ServeJSON()
}

func (this *UserController) Logout() {
    v := org.User{}
	this.ParseForm(&v)
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
	    this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return
	}
	this.ServeOk("登出成功")
}

func (this *UserController) Create() {
    var v org.User
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.UserName, "user_name")
	valid.Required(v.Password, "password")
	valid.Required(v.PasswordConfirm, "password_confirm")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return	
	} 
	if v.Password != v.PasswordConfirm {
	    this.ServeOk("password and password_confirm are not equal")
		return
	}
	// init org
	/*
	companyId, _:= org.InitDefaultCompany(v.UserName, v.Password)
    roleId, _:= org.InitDefaultRole(companyId)
	userId, err := org.InitDefaultUser(companyId, v.UserName, v.Password, roleId)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	*/
	rsp := struct {
	    UserId    int64       `json:"user_id"`
	    Created   time.Time   `json:"created"`
	}{UserId:1, Created:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *UserController) Put() {
	//curPartnerId := this.Ctx.Input.GetData("curCompanyId").(int)
	curUserId := this.Ctx.Input.GetData("curUserId").(int)
	v := org.User{}
	v.UserId = int64(curUserId)
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.UserId, "user_id")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	var updateFields []string
	if len(v.UserName) > 0 {
	   updateFields = append(updateFields, "user_name")
	}
	if len(v.Password) > 0 && len(v.PasswordConfirm) > 0 {
	    user, err := org.GetUserByUserId(v.UserId)
		if err != nil {
		    this.ServeError(err.Error())
			return
		}
	    v.PasswordHashed = org.EncryptPassword(user.Salt, v.Password)
	    updateFields = append(updateFields, "password_hashed")
	}
	if len(v.Mobile) > 0 {
	   updateFields = append(updateFields, "mobile")
	}
	if len(v.Avatar) > 0 {
	   updateFields = append(updateFields, "avatar")
	}
	if len(v.Email) > 0 {
	   updateFields = append(updateFields, "email")
	}
	if err := org.UpdateUsersById(&v, updateFields...); err != nil{
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
		UserId     int64       `json:"user_id"`
		Modified   time.Time   `json:"modified"`
	}{UserId:v.UserId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *UserController) GetCurrentUser() {
	curUserId := int64(this.Ctx.Input.GetData("curUserId").(int))
	usr, err := org.GetUserByUserId(int64(curUserId))
	if err != nil {
		this.ServeError("用户信息不存在")
	    return
	}
	this.Data["json"] = usr
	this.ServeJSON()
}

func (this *UserController) GetSubUsers() {
	partnerId := int64(this.Ctx.Input.GetData("curCompanyId").(int))
	v := struct {
	    RoleId    int64 `form:"role_id" valid:"Required"`
		PageSize  int   `form:"page_size"`
		PageNo    int   `form:"page_no"`
	}{PageSize:100, PageNo:1}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	if ok := org.CheckRoleExistByPartner(int64(partnerId), v.RoleId); !ok {
	    this.ServeError("role_id is invalid")
	    return
	}
	v.PageNo = v.PageNo - 1     //为了计算offset
	offset := v.PageNo*v.PageSize
	limit := v.PageSize
	list, err := org.GetSubUsers(v.RoleId, offset, limit)
	if err != nil {
	    this.ServeError(err.Error())
	    return
	}
	cnt := len(list)
	rsp := struct {
		TotalCount int          `json:"total_count"`
		Users      []*org.User  `json:"users"`
	}{TotalCount: cnt, Users: list}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *UserController) GetUserBasicInfo() {
	//curUserId := this.Ctx.Input.GetData("curUserId").(int)
	openId := this.GetString("open_id")
	userIdStr := this.GetString("user_id")
	if openId == "" && userIdStr == ""{
	    this.ServeError("open_id and user_id is null")
	    return
	}
	user, err := org.GetUserIdByOpenIdOrUserId(openId, userIdStr)
	if err != nil {
		this.ServeError("用户信息不存在")
		return
	}
	rsp := struct {
	    UserId    string   `json:"user_id"`
	    OpenId    string   `json:"open_id"`
		NickName  string   `json:"nick_name"`
		AvatarURL string   `json:"avatar_url"`
	}{UserId:strconv.FormatInt(user.UserId, 10),OpenId:openId,NickName:user.NickName,AvatarURL:user.Avatar}
	this.Data["json"] = rsp
	this.ServeJSON()
}

// 获取所有用户
func (this *UserController) GetAllUsers() {
	query,_,fields,order_by,offset,limit,err := this.GetQueryPara()
	if err != nil {
	   this.ServeError(err.Error())
	   return
	}
	l, cnt, err := org.GetAllUsers(query,fields,order_by,offset,limit)
	if err != nil {
	    this.ServeError(err.Error())
	    return
	}
	r := struct {
		TotalCount int64       `json:"total_count"`
		Users      []*org.User `json:"users"`
	}{TotalCount: cnt, Users: l}
	this.Data["json"] = r
	this.ServeJSON()
}

func (this *UserController) Enable() {
	userId, err := this.GetInt("user_id")
	if err != nil {
	    this.ServeError(err.Error())
	    return
	}
	err = org.ActivedUser(0, userId, true)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
	    UserId     int         `json:"user_id"`
	    Modified   time.Time   `json:"modified"`
	}{UserId:userId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *UserController) Disable() {
	userId, err := this.GetInt("user_id")
	if err != nil {
	    this.ServeError(err.Error())
	    return
	}
	err = org.ActivedUser(0, userId, false)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
	    UserId     int         `json:"user_id"`
	    Modified   time.Time   `json:"modified"`
	}{UserId:userId, Modified:time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *UserController) CreateApiUser() {
    v := struct {
		PartnerId        int64   `form:"partner_id"`
		ApiId            string  `form:"api_id"`
		ApiSecret        string  `form:"api_secret"`
		ApiSecretConfirm string  `form:"api_secret_confirm"`
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.PartnerId, "partner_id")
	valid.Required(v.ApiId,  "api_id")
	valid.Required(v.ApiSecret,  "api_secret")
	valid.Required(v.ApiSecretConfirm, "api_secret_confirm")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return	
	} 
	if v.ApiSecret != v.ApiSecretConfirm {
	    this.ServeOk("api_secret and api_secret_confirm are not equal")
		return
	}
	if _, err := org.GetPartnerById(v.PartnerId); err != nil {
	    this.ServeError(err.Error())
		return
	}
	roleIdStr := ""
	role, err := org.GetRoleByPartnerIdAndName(v.PartnerId, "API访问接口")
	if err != nil {
        roleId, err := org.InitDefaultApiRole(v.PartnerId)
		if err != nil {
			this.ServeError(err.Error())
			return
		}
		roleIdStr = strconv.FormatInt(roleId, 10)
    }else{
	    roleIdStr = strconv.FormatInt(role.RoleId, 10)
	}
	userId, _:= misc.GetUserNo()
	user := &org.User{UserId:userId,PartnerId:v.PartnerId,UserName:v.ApiId,Password:v.ApiSecret,RoleIds:roleIdStr,IsOpenApi:1}
	_, err = org.CreateUser(user)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
	    UserId    int64   `json:"user_id"`
	    ApiId     string  `json:"api_id"`
		ApiSecret string  `json:"api_secret"`
	}{UserId:userId, ApiId:v.ApiId, ApiSecret:v.ApiSecret}
	this.Data["json"] = rsp
	this.ServeJSON()
}


func (this *UserController) GetApiToToken() {
	v := struct {
		ApiId            string  `form:"api_id"`
		ApiSecret        string  `form:"api_secret"`
		Salt             string  `form:"-"`
		PasswordHashed   string  `form:"-"`
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Required(v.ApiId, "api_id")
	valid.Required(v.ApiSecret, "api_secret")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return
	}
	user, err := org.GetUserByUsername(v.ApiId)	 
	if err != nil {
		this.ServeError("用户信息不存在")
		return 
	}
    /*	
	if !user.Activated {
		this.ServeError("用户已经停用，请联系管理员")
		return 
	}
	*/
	v.Salt = user.Salt            //读取原有的加密盐
	v.PasswordHashed = org.EncryptPassword(user.Salt, v.ApiSecret)
	if v.PasswordHashed != user.PasswordHashed {
		this.ServeError("密码错误")
		return
	}
	token := jwt.New(jwt.GetSigningMethod("HS256"))
	claims := token.Claims.(jwt.MapClaims)
	claims["CurrentUser"] = struct {
	    Id int64
		CompanyId int
		Role      int
	}{Id: user.UserId, CompanyId: int(user.PartnerId),Role:9}
	claims["exp"] = time.Now().UTC().Add(time.Hour * 2 * 1).Unix()
	tokenSecret := beego.AppConfig.String("AuthTokenSecret")
	tokenString, err := token.SignedString([]byte(tokenSecret))
	if err != nil {
		this.ServeError("登录失败，请稍后再试")
		return
	}
	result := struct {
		Token     string `json:"token"`
		ExpiresIn int    `json:"expires_in"`
	}{Token: tokenString, ExpiresIn: 7200}
	this.Data["json"] = result
	this.ServeJSON()
}
